import indicadores.*
import hce.core.composition.*
import hce.core.composition.content.* 
import hce.CustomQueriesService
import hce.HceService
import org.openehr.am.archetype.Archetype
import archetype_repository.ArchetypeManager
import templates.TemplateManager
import java.util.LinkedHashMap 
import binding.CtrlTerminologia
import hce.core.support.identification.TerminologyID
import util.StringEntero
import com.thoughtworks.xstream.XStream

 
class IndicadoresController { 

    def index = {
        //redirect(action:'index')
        render(view: 'index')
    }

    def ejemploInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.ejemplo'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.cantExamenesPorDiagnostico'),
                idIndicador: "ejemplo",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: true,
                cantidadDiagnosticos: 10])
    }

    def tiempoEtapaCilcoAtencionInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.tiempoEtapaCilcoAtencion'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.tiempoEtapaCilcoAtencion'),
                idIndicador: "tiempoEtapaCilcoAtencion",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: false])
    }

    def gravedadPacienteAlLlegarInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.gravedadPacienteAlLlegar'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.gravedadPacienteAlLlegar'),
                idIndicador: "gravedadPacienteAlLlegar",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: false])
    }

    def pasesABlockPorTriageInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.pasesABlockPorTriage'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.pasesABlockPorTriage'),
                idIndicador: "pasesABlockPorTriage",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: false])
    }

    def pasesABlockPorGravedadInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.pasesABlockPorGravedad'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.pasesABlockPorGravedad'),
                idIndicador: "pasesABlockPorGravedad",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: false])
    }

    def pasesABlockPorGravedadYDiagnosticoInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.pasesABlockPorGravedadYDiagnostico'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.pasesABlockPorGravedadYDiagnostico'),
                idIndicador: "pasesABlockPorGravedadYDiagnostico",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: true,
                cantidadDiagnosticos: 10])
    }

    def cantEpisodiosPorDiagnosticoInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.cantEpisodiosPorDiagnostico'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.cantEpisodiosPorDiagnostico'),
                idIndicador: "cantEpisodiosPorDiagnostico",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: true,
                cantidadDiagnosticos: 10])
    }

    def cantExamenesPorDiagnosticoInicio = {
        render(view: 'list', model:[
                nombreIndicador: message(code: 'indicadores.nombreIndicador.cantExamenesPorDiagnostico'),
                descripcionIndicador: message(code: 'indicadores.descripcionIndicador.cantExamenesPorDiagnostico'),
                idIndicador: "cantExamenesPorDiagnostico",
                estructuraTabla: null,
                resDatos: null,
                mostrarDatos: false,
                filtroCantDiagnosticos: true,
                cantidadDiagnosticos: 10])
    }

    def list = {

        CabezalFila cabFila1 = new CabezalFila(nombre: "Sexo", opciones: ["Hombre", "Mujer"])
        CabezalFila cabFila2 = new CabezalFila(nombre: "Edad", opciones: ["0-30", ">30"])
        CabezalFila cabFila3 = new CabezalFila(nombre: "Opción", opciones: ["ABC", "XYZ"])
        CabezalFila cabFila4 = new CabezalFila(nombre: "Tiempo", opciones: ["1 hora", "1 dia", "1 semana"])
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "Tipo Trauma", opciones: ["A", "B"])
        CabezalColumna cabColumna2 = new CabezalColumna(nombre: "Gravedad", opciones: ["1", "2"])
        CabezalColumna cabColumna3 = new CabezalColumna(nombre: "Nivel", opciones: ["H111", "H222", "H333"])
        CabezalColumna cabColumna4 = new CabezalColumna(nombre: "AAA", opciones: ["G1", "G2", "G3"])
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1, cabFila2, cabFila3, cabFila4], cabezalesColumna: [cabColumna1, cabColumna2, cabColumna3, cabColumna4])

        //String[][][][][][][][] datos = new String [3][3][2][2][3][2][2][2]// AAA, Nivel, Gravedad, TipoTrauma, Tiempo, Opcion, Edad, Sexo  //String[2][2][2][3][2][2][3][3]
        int cantDatos = 3*3*2*2*3*2*2*2 // AAA, Nivel, Gravedad, TipoTrauma, Tiempo, Opcion, Edad, Sexo
        String[] datos = new String [cantDatos]
        int indiceDatos = 0
        for(int i8=0; i8 < 2; i8++){
            for(int i7=0; i7 < 2; i7++){
                for(int i6=0; i6 < 2; i6++){
                    for(int i5=0; i5 < 3; i5++){
                        for(int i4=0; i4 < 2; i4++){
                            for(int i3=0; i3 < 2; i3++){
                                for(int i2=0; i2 < 3; i2++){
                                    for(int i1=0; i1 < 3; i1++){
                                        datos[indiceDatos++] = "" + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8
                                        //indiceDatos++
                                        //String dato = "" + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8//i1.toString() + i2.toString() + i3.toString() + i4.toString() + i5.toString() + i6.toString() + i7.toString() + i8.toString()
                                        //datos[i1][i2][i3][i4][i5][i6][i7][i8] = dato
                                        //println "AAA: " + i1.toString() + i2.toString() + i3.toString() + i4.toString() + i5.toString() + i6.toString() + i7.toString() + i8.toString()
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return [
            nombreIndicador: message(code: 'indicadores.nombreIndicador.ejemplo'),
            idIndicador: "ejemplo",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: false,
            cantEpisodios: 1000,
            filtroCantDiagnosticos: false]
    }

    //---------------------------------------------------------------------------------------------------------

    def tiempoEtapaCilcoAtencion = {   

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        def desde = obtenerFechaDesde(params)
        def hasta = obtenerFechaHasta(params)

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                } 
            }

            //like('title', '%Groovy%') //TODO filtrar los que tengan triage
        }

        CabezalFila cabFila1 = new CabezalFila(nombre: "", opciones: ["Tiempo de Permanencia Promedio"])
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "Etapa Ciclo de Atención", opciones: ["Admisión/Triage", "Evaluación", "Espera luego de Evaluación"])
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1], cabezalesColumna: [cabColumna1])

        String tiempoPromedioAdmision = customQueriesService.getTiempoPermanenciaPromedioEtapaAdmisionEpisodio(listaComp)
        String tiempoPromedioEvaluacion = customQueriesService.getTiempoPermanenciaPromedioEtapaEvaluacionEpisodio(listaComp)
        String tiempoPromedioLuegoDeEvaluacion = customQueriesService.getTiempoPermanenciaPromedioEtapaEsperaLuegoDeEvaluacionEpisodio(listaComp)

        if (!tiempoPromedioAdmision)
            tiempoPromedioAdmision = "No hay Datos"
        if (!tiempoPromedioEvaluacion)
            tiempoPromedioEvaluacion = "No hay Datos"
        if (!tiempoPromedioLuegoDeEvaluacion)
            tiempoPromedioLuegoDeEvaluacion = "No hay Datos"

        int cantDatos = cabColumna1.opciones.length // Etapa Ciclo de Atención, Tiempo de Permanencia Promedio
        String[] datos = new String [cantDatos]
        def indiceDatos = 0
        datos[indiceDatos++] = "" + tiempoPromedioAdmision
        datos[indiceDatos++] = "" + tiempoPromedioEvaluacion
        datos[indiceDatos++] = "" + tiempoPromedioLuegoDeEvaluacion


        //return [estructuraTabla: tablaResult, resDatos: datos]
        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.tiempoEtapaCilcoAtencion'),
            idIndicador: "tiempoEtapaCilcoAtencion",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: false,
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //---------------------------------------------------------------------------------------------------------

    def gravedadPacienteAlLlegar = {

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        Date desde = obtenerFechaDesde(params)
        Date hasta = obtenerFechaHasta(params)

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                }
            }

            //like('title', '%Groovy%') //TODO filtrar los que tengan triage
        }

        // Obtengo el arquetipo que define el triage
        String templateId = "INGRESO-triage" 
        def template = TemplateManager.getInstance().getTemplate(templateId)
        def archetype = ArchetypeManager.getInstance().getArchetype(template.getRootArchetypeId()) // deberia ser: openEHR-EHR-EVALUATION.triage_trauma.v1

        //imprimirObjetoXML(archetype.getOntology().getTermDefinitionsList())

        // Obtengo los diferentes valores que puede tomar el triage
        //at0003, at0004, at0005, at0006, at0007
        TerminologyID termId = new TerminologyID(name: "local", versionId: "1.0.0")
        CtrlTerminologia ctrlTerm = CtrlTerminologia.getInstance()
        String termino3 = ctrlTerm.getTermino(termId, "at0003", archetype, session.locale)
        String termino4 = ctrlTerm.getTermino(termId, "at0004", archetype, session.locale)
        String termino5 = ctrlTerm.getTermino(termId, "at0005", archetype, session.locale)
        String termino6 = ctrlTerm.getTermino(termId, "at0006", archetype, session.locale)
        String termino7 = ctrlTerm.getTermino(termId, "at0007", archetype, session.locale)

        // Creo una instancia de TablaResult adecuada para el indicador
        CabezalFila cabFila1 = new CabezalFila(nombre: "", opciones: ["Cantidad de Pacientes"])
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "Gravedad", opciones: [termino3, termino4, termino5, termino6, termino7]) // TODO obtener de arquetipo openEHR-EHR-EVALUATION.triage_trauma.v1
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1], cabezalesColumna: [cabColumna1])

        // Creo un mapero que tendra todas las opciones del triage mapeadas a un entero.
        // Servira para contar la cantidad de Episodios que hay para cada opcion del Triage
        LinkedHashMap<String, Integer> mapaGravedadaCantidad = new LinkedHashMap<String, Integer>()
        mapaGravedadaCantidad.put(termino3, 0)
        mapaGravedadaCantidad.put(termino4, 0)
        mapaGravedadaCantidad.put(termino5, 0)
        mapaGravedadaCantidad.put(termino6, 0)
        mapaGravedadaCantidad.put(termino7, 0) 

        // Para cada Episodio de Trauma (que filtramos anteriormente), me fijo que clasificación de
        // triage tiene y sumo en uno el contador respectivo del mapeo mapaGravedadaCantidad
        listaComp.each{comp ->
            String codeStringGravedad = customQueriesService.getTriageClasification(comp) // Obtengo clasificación de triage (el codigo)
            if (codeStringGravedad != null){ // Si tiene clasificacion de triage
                def archetypeTermGravedad = archetype.ontology.termDefinition(session.locale.language, codeStringGravedad) // FIXME cambiar el language por el idioma seleccionado por el usuario
                String gravedad = archetypeTermGravedad.items.get("text")
                if (gravedad != null){
                    String key = gravedad
                    mapaGravedadaCantidad.put(key, mapaGravedadaCantidad.get(key) + 1) // Actualizo el mapeo
                }
            }
        }

        //imprimirObjetoXML(mapaGravedadaCantidad)

        // Llenos el array datos que enviare a la vista
        String[] datos = new String [cabColumna1.opciones.length]
        int indiceDatos = 0
        cabColumna1.opciones.each{op ->
            datos[indiceDatos++] = mapaGravedadaCantidad.get(op).toString()
        }

        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.gravedadPacienteAlLlegar'),
            idIndicador: "gravedadPacienteAlLlegar",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: false,
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //--------------------------------------------------------------------------

    def pasesABlockPorTriage = {

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        def desde = obtenerFechaDesde(params)
        def hasta = obtenerFechaHasta(params)

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                }
            }

            //like('title', '%Groovy%') //TODO filtrar los que tengan triage
        }

        // Obtengo el arquetipo que define el triage
        String templateId = "INGRESO-triage"
        def template = TemplateManager.getInstance().getTemplate(templateId)
        def archetype = ArchetypeManager.getInstance().getArchetype(template.getRootArchetypeId()) // deberia ser: openEHR-EHR-EVALUATION.triage_trauma.v1

        // Obtengo los diferentes valores que puede tomar el triage
        //at0003, at0004, at0005, at0006, at0007
        TerminologyID termId = new TerminologyID(name: "local", versionId: "1.0.0")
        CtrlTerminologia ctrlTerm = CtrlTerminologia.getInstance()
        String termino3 = ctrlTerm.getTermino(termId, "at0003", archetype, session.locale)
        String termino4 = ctrlTerm.getTermino(termId, "at0004", archetype, session.locale)
        String termino5 = ctrlTerm.getTermino(termId, "at0005", archetype, session.locale)
        String termino6 = ctrlTerm.getTermino(termId, "at0006", archetype, session.locale)
        String termino7 = ctrlTerm.getTermino(termId, "at0007", archetype, session.locale)

        // Creo una instancia de TablaResult adecuada para el indicador
        CabezalFila cabFila1 = new CabezalFila(nombre: "", opciones: ["Cant. Pases a Block Quirurgico"])
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "Clasificacion Triage", opciones: [termino3, termino4, termino5, termino6, termino7]) // TODO obtener de arquetipo openEHR-EHR-EVALUATION.triage_trauma.v1
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1], cabezalesColumna: [cabColumna1])

        // Creo un mapero que tendra todas las opciones del triage mapeadas a un entero.
        // Servira para contar la cantidad de Episodios que hay para cada opcion del Triage
        LinkedHashMap<String, Integer> mapaGravedadaCantidad = new LinkedHashMap<String, Integer>()
        mapaGravedadaCantidad.put(termino3, 0)
        mapaGravedadaCantidad.put(termino4, 0)
        mapaGravedadaCantidad.put(termino5, 0)
        mapaGravedadaCantidad.put(termino6, 0)
        mapaGravedadaCantidad.put(termino7, 0)

        // Para cada Episodio de Trauma (que filtramos anteriormente), me fijo si tuvo pase a
        // Block Quirúrgico, y si tuvo, me fijo que clasificación de triage tiene y sumo en uno
        // el contador respectivo del mapeo mapaGravedadaCantidad
        listaComp.each{comp ->
            List<String> movimientosEpisodios = customQueriesService.getMovimientosEpisodio(comp);
            if(movimientosEpisodios.contains("at0008")){ // Si tuvo pase a blok Quirúrgico (el codeString de block Quirúrgico es at0008)
                String codeStringGravedad = customQueriesService.getTriageClasification(comp) // Obtengo clasificación de triage (el codigo)
                if (codeStringGravedad != null){ // Si tiene clasificacion de triage
                    def archetypeTermGravedad = archetype.ontology.termDefinition(session.locale.language, codeStringGravedad) // FIXME cambiar el language por el idioma seleccionado por el usuario
                    String gravedad = archetypeTermGravedad.items.get("text")
                    if (gravedad != null){
                        String key = gravedad
                        mapaGravedadaCantidad.put(key, mapaGravedadaCantidad.get(key) + 1) // Actualizo el mapeo
                    }
                }
            }
        }

        //imprimirObjetoXML(mapaGravedadaCantidad)

        //(Composition).[(ContentItem)content](Instruction).[(Activity)activities].(ItemTree)description.[(Item)items](Element).(DvCodedText)value.(CodePhrase)definingCode.(String)codeString == at0008

        // Llenos el array datos que enviare a la vista
        String[] datos = new String [cabColumna1.opciones.length] 
        int indiceDatos = 0
        cabColumna1.opciones.each{op ->
            datos[indiceDatos++] = mapaGravedadaCantidad.get(op).toString()
        } 

        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.pasesABlockPorTriage'),
            idIndicador: "pasesABlockPorTriage",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: false,
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //--------------------------------------------------------------------------

    def pasesABlockPorGravedad = {

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        def desde = obtenerFechaDesde(params)
        def hasta = obtenerFechaHasta(params)

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                }
            }

            //like('title', '%Groovy%') //TODO filtrar los que tengan triage
        }

        // Cada termino equivale a los diferentes valores que puede tomar el RTS
        TerminologyID termId = new TerminologyID(name: "local", versionId: "1.0.0")
        CtrlTerminologia ctrlTerm = CtrlTerminologia.getInstance()
        String termino1 = "1"
        String termino2 = "2"
        String termino3 = "3"
        String termino4 = "4"
        String termino5 = "5"
        String termino6 = "6"
        String termino7 = "7"
        String termino8 = "8"
        String termino9 = "9"
        String termino10 = "10"
        String termino11 = "11"
        String termino12 = "12"

        // Creo una instancia de TablaResult adecuada para el indicador
        CabezalFila cabFila1 = new CabezalFila(nombre: "", opciones: ["Cant. Pases a Block Quirurgico"])
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "RTS", opciones: [termino1, termino2, termino3, termino4, termino5, termino6, termino7, termino8, termino9, termino10, termino11, termino12])
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1], cabezalesColumna: [cabColumna1])

        // Creo un mapero que tendra todas las opciones del triage mapeadas a un entero.
        // Servira para contar la cantidad de Episodios que hay para cada opcion del Triage
        LinkedHashMap<String, Integer> mapaGravedadaCantidad = new LinkedHashMap<String, Integer>()
        mapaGravedadaCantidad.put(termino1, 0)
        mapaGravedadaCantidad.put(termino2, 0)
        mapaGravedadaCantidad.put(termino3, 0)
        mapaGravedadaCantidad.put(termino4, 0)
        mapaGravedadaCantidad.put(termino5, 0)
        mapaGravedadaCantidad.put(termino6, 0)
        mapaGravedadaCantidad.put(termino7, 0)
        mapaGravedadaCantidad.put(termino8, 0)
        mapaGravedadaCantidad.put(termino9, 0)
        mapaGravedadaCantidad.put(termino10, 0)
        mapaGravedadaCantidad.put(termino11, 0)
        mapaGravedadaCantidad.put(termino12, 0)

        // Para cada Episodio de Trauma (que filtramos anteriormente), me fijo si tuvo pase a
        // Block Quirúrgico, y si tuvo, me fijo que RTS tiene y sumo en uno
        // el contador respectivo del mapeo mapaGravedadaCantidad
        listaComp.each{comp ->
            List<String> movimientosEpisodios = customQueriesService.getMovimientosEpisodio(comp);
            if(movimientosEpisodios.contains("at0008")){ // Si tuvo pase a blok Quirúrgico (el codeString de block Quirúrgico es at0008)
                Integer valorRTS = customQueriesService.getRTSEpisodio(comp) // Obtengo clasificación de triage (el codigo)
                if (valorRTS != null){ // Si tiene clasificacion RTS
                    String key = valorRTS.toString()
                    mapaGravedadaCantidad.put(key, mapaGravedadaCantidad.get(key)+1) // Actualizo el mapeo
                }
            }
        }

        //imprimirObjetoXML(mapaGravedadaCantidad)

        //(Composition).[(ContentItem)content](Instruction).[(Activity)activities].(ItemTree)description.[(Item)items](Element).(DvCodedText)value.(CodePhrase)definingCode.(String)codeString == at0008

        // Llenos el array datos que enviare a la vista
        String[] datos = new String [cabColumna1.opciones.length]
        int indiceDatos = 0
        cabColumna1.opciones.each{op ->
            datos[indiceDatos++] = mapaGravedadaCantidad.get(op).toString()
        }

        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.pasesABlockPorGravedad'),
            idIndicador: "pasesABlockPorGravedad",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: false,
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------

    def pasesABlockPorGravedadYDiagnostico = {

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        int cantDiagnosticos = obtenerCantDiagnosticos(params)
        def desde = obtenerFechaDesde(params)
        def hasta = obtenerFechaHasta(params)
    

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                }
            }

            //like('title', '%Groovy%') //TODO filtrar los que tengan triage
        }

        //----------------------------------------------------------------------

        // Obtengo una lista de elementos (StringEntero) con los N diagnosticos mas frecuentes
        // junto con sus respectivas cantidad de apariciones ordenado en forma descendente
        List<StringEntero> listDiagCantOrdenada = customQueriesService.getDiagnosticosMasFrecuetes(listaComp, cantDiagnosticos)

        // Armo una lista que tenga solo los nombres de los tipos de trauma (Diagnostico)
        List<StringEntero> nombreTiposTraumaMasFrecuentes = new LinkedList<String>()
        listDiagCantOrdenada.each{se ->
            nombreTiposTraumaMasFrecuentes.add(se.str)
        }

        // Creo una instancia de TablaResult adecuada para el indicador
        String[] opcTiposTrauma = nombreTiposTraumaMasFrecuentes.toArray()

        //----------------------------------------------------------------------

        // Cada termino equivale a los diferentes valores que puede tomar el RTS
        TerminologyID termId = new TerminologyID(name: "local", versionId: "1.0.0")
        CtrlTerminologia ctrlTerm = CtrlTerminologia.getInstance()
        String termino1 = "1"
        String termino2 = "2"
        String termino3 = "3"
        String termino4 = "4"
        String termino5 = "5"
        String termino6 = "6"
        String termino7 = "7"
        String termino8 = "8"
        String termino9 = "9"
        String termino10 = "10"
        String termino11 = "11"
        String termino12 = "12"

        // Creo una instancia de TablaResult adecuada para el indicador
        CabezalFila cabFila1 = new CabezalFila(nombre: "", opciones: ["Cant. Pases a Block Quirurgico"])
        CabezalFila cabFila2 = new CabezalFila(nombre: "Diagnosticos", opciones: opcTiposTrauma)
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "RTS", opciones: [termino1, termino2, termino3, termino4, termino5, termino6, termino7, termino8, termino9, termino10, termino11, termino12])
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1, cabFila2], cabezalesColumna: [cabColumna1])

        // Creo un mapero que tendra paca cada par Diagnostico-Gravedad un valor asociado (inicializad en 0)
        // Servira para contar la cantidad de Episodios que hay para cada par Diagnostico-Gravedad
        LinkedHashMap<String, LinkedHashMap<String, Integer>> mapaDiagnosticoGravCant = new LinkedHashMap<String, LinkedHashMap<String, Integer>>()
        opcTiposTrauma.each{tipoTrauma ->
            LinkedHashMap<String, Integer> mapaGravedadaCantidad = new LinkedHashMap<String, Integer>()
            mapaGravedadaCantidad.put(termino1, 0)
            mapaGravedadaCantidad.put(termino2, 0)
            mapaGravedadaCantidad.put(termino3, 0)
            mapaGravedadaCantidad.put(termino4, 0)
            mapaGravedadaCantidad.put(termino5, 0)
            mapaGravedadaCantidad.put(termino6, 0)
            mapaGravedadaCantidad.put(termino7, 0)
            mapaGravedadaCantidad.put(termino8, 0)
            mapaGravedadaCantidad.put(termino9, 0)
            mapaGravedadaCantidad.put(termino10, 0)
            mapaGravedadaCantidad.put(termino11, 0)
            mapaGravedadaCantidad.put(termino12, 0)
            mapaDiagnosticoGravCant.put(tipoTrauma, mapaGravedadaCantidad)
        }

        // Para cada Episodio de Trauma (que filtramos anteriormente), me fijo si tuvo pase a
        // Block Quirúrgico, y si tuvo, me fijo que RTS tiene y sumo en uno
        // el contador respectivo del mapeo mapaGravedadaCantidad
        listaComp.each{comp ->
            List<String> movimientosEpisodios = customQueriesService.getMovimientosEpisodio(comp);
            if(movimientosEpisodios.contains("at0008")){ // Si tuvo pase a blok Quirúrgico (el codeString de block Quirúrgico es at0008)
                List<String> listaDiagnosticosEpisodio = customQueriesService.getDiagnosticosEpisodio(comp)
                Integer RTS = customQueriesService.getRTSEpisodio(comp)
                listaDiagnosticosEpisodio.each{dignostico ->
                    def mapaGravCant = mapaDiagnosticoGravCant.get(dignostico)
                    if (mapaGravCant != null){ // Por si el diagnostico no es uno de los que tuvo mas ocurrencias
                        def newCant = mapaGravCant.get(RTS.toString()) + 1 // Aumento en 1 la cantidad de episodios para el diagnostico y valor de RTS correspondiente
                        mapaGravCant.put(RTS.toString(), newCant) // Reflejo el nuevo vcalor de cantidad en el mapeo correspondiente
                        mapaDiagnosticoGravCant.put(dignostico, mapaGravCant)
                    }
                }
            }
        }

        // Llenos el array datos que enviare a la vista
        String[] datos = new String [cabFila2.opciones.length * cabColumna1.opciones.length]
        int indiceDatos = 0
        cabFila2.opciones.each{opCabFila2 ->
            LinkedHashMap<String, Integer> mapaGravedadaCantidad = mapaDiagnosticoGravCant.get(opCabFila2)
            cabColumna1.opciones.each{opCabColumna1 ->
                datos[indiceDatos++] = mapaGravedadaCantidad.get(opCabColumna1).toString()//mapaGravedadaCantidad.get(op).toString()
            }
        }
        
        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.pasesABlockPorGravedadYDiagnostico'),
            idIndicador: "pasesABlockPorGravedadYDiagnostico",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: true,
            cantidadDiagnosticos: obtenerCantDiagnosticos(params),
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //--------------------------------------------------------------------------

    def cantEpisodiosPorDiagnostico = {

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        int cantDiagnosticos = obtenerCantDiagnosticos(params)
        def desde = obtenerFechaDesde(params)
        def hasta = obtenerFechaHasta(params)

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                }
            }
            //like('atributo', valor) //TODO mas filtros
        }

        // Obtengo una lista de elementos (StringEntero) con los N diagnosticos mas frecuentes
        // junto con sus respectivas cantidad de apariciones ordenado en forma descendente
        List<StringEntero> listDiagCantOrdenada = customQueriesService.getDiagnosticosMasFrecuetes(listaComp, cantDiagnosticos)

        // Armo una lista que tenga solo los nombres de los tipos de trauma (Diagnostico)
        List<StringEntero> nombreTiposTraumaMasFrecuentes = new LinkedList<String>()
        listDiagCantOrdenada.each{se ->
            nombreTiposTraumaMasFrecuentes.add(se.str)
        }

        // Creo una instancia de TablaResult adecuada para el indicador
        String[] opcTiposTrauma = nombreTiposTraumaMasFrecuentes.toArray()
        CabezalFila cabFila1 = new CabezalFila(nombre: "Tipos de Trauma", opciones: opcTiposTrauma)
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "", opciones: ["Cant. de Episodios"])
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1], cabezalesColumna: [cabColumna1])

        // Llenos el array datos que enviare a la vista
        String[] datos = new String [listDiagCantOrdenada.size()]
        int indiceDatos = 0
        listDiagCantOrdenada.each{se -> 
            datos[indiceDatos++] = se.entero.toString()
        }

        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.cantEpisodiosPorDiagnostico'),
            idIndicador: "cantEpisodiosPorDiagnostico",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: true,
            cantidadDiagnosticos: obtenerCantDiagnosticos(params),
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //--------------------------------------------------------------------------

    def cantExamenesPorDiagnostico = {

        CustomQueriesService customQueriesService = new CustomQueriesService()
        HceService hceService =  new HceService()
        customQueriesService.hceService = hceService

        // Obtengo parametros de la consulta
        int cantDiagnosticos = obtenerCantDiagnosticos(params)
        def desde = obtenerFechaDesde(params)
        def hasta = obtenerFechaHasta(params)

        // Obtengo datos para el indicador
        // Todos los Episodios de Trauma (representados por Compositions) que hayan sido iniciados
        // entre las fechas "desde" y "hasta"
        def listaComp = Composition.withCriteria {
            def stringDesde = getStringFecha(desde)
            def stringHasta = getStringFecha(hasta)
            context{
                startTime{
                    between('value', stringDesde, stringHasta)
                }
            }

            //like('title', '%Groovy%') //TODO filtrar los que tengan triage
        }

        //----------------------------------------------------------------------

        // Obtengo una lista de elementos (StringEntero) con los N diagnosticos mas frecuentes
        // junto con sus respectivas cantidad de apariciones ordenado en forma descendente
        List<StringEntero> listDiagCantOrdenada = customQueriesService.getDiagnosticosMasFrecuetes(listaComp, cantDiagnosticos)

        // Armo una lista que tenga solo los nombres de los tipos de trauma (Diagnostico)
        List<StringEntero> nombreTiposTraumaMasFrecuentes = new LinkedList<String>()
        listDiagCantOrdenada.each{se ->
            nombreTiposTraumaMasFrecuentes.add(se.str)
        }

        // Creo una instancia de TablaResult adecuada para el indicador
        String[] opcTiposTrauma = nombreTiposTraumaMasFrecuentes.toArray()
 
        //----------------------------------------------------------------------

        // Cada termino equivale a los diferentes Examenes (por ahora discrimino entre
        // examenes de laboratorio y examenes imagenológicos )
        TerminologyID termId = new TerminologyID(name: "local", versionId: "1.0.0")
        CtrlTerminologia ctrlTerm = CtrlTerminologia.getInstance()
        String termino1 = "Imagenologicos"
        String termino2 = "Laboratorio"

        // Creo una instancia de TablaResult adecuada para el indicador
        //CabezalFila cabFila1 = new CabezalFila(nombre: "", opciones: ["Pedidos de Examenes"])
        CabezalFila cabFila1 = new CabezalFila(nombre: "Diagnosticos", opciones: opcTiposTrauma)
        CabezalColumna cabColumna1 = new CabezalColumna(nombre: "Examenes", opciones: [termino1, termino2])
        // El orden en el arreglo cabezales importa
        TablaResult tablaResult = new TablaResult(cabezalesFila: [cabFila1], cabezalesColumna: [cabColumna1])

        // Creo un mapero que tendra paca cada par Diagnostico-Gravedad un valor asociado (inicializad en 0)
        // Servira para contar la cantidad de Episodios que hay para cada par Diagnostico-Gravedad
        LinkedHashMap<String, LinkedHashMap<String, Integer>> mapaDiagnosticoExaCant = new LinkedHashMap<String, LinkedHashMap<String, Integer>>()
        opcTiposTrauma.each{tipoTrauma ->
            LinkedHashMap<String, Integer> mapaExamenCantidad = new LinkedHashMap<String, Integer>()
            mapaExamenCantidad.put(termino1, 0)
            mapaExamenCantidad.put(termino2, 0)
            mapaDiagnosticoExaCant.put(tipoTrauma, mapaExamenCantidad)
        }

        // Para cada Episodio de Trauma (que filtramos anteriormente), obtengo su lista de examenes imagenologicos
        // y su lista de examenes de laboratorio. Cuento la cantidad de cada uno de estos y actualizo para cada
        // diagnostico del episodio la cantidad de cada examen en el mapeo mapaDiagnosticoExaCant
        listaComp.each{comp ->
            List<String> examenesImagenologicosEpisodio = customQueriesService.getExamenesImagenologicosEpisodio(comp)
            List<String> examenesLaboratorioEpisodio = customQueriesService.getExamenesLaboratorioEpisodio(comp)
            List<String> listaDiagnosticosEpisodio = customQueriesService.getDiagnosticosEpisodio(comp)
            listaDiagnosticosEpisodio.each{dignostico ->
                def mapaExaCant = mapaDiagnosticoExaCant.get(dignostico)
                if (mapaExaCant != null){ // Si el diagnostico no es uno de los N con major cantidad de ocurrencias no estara en el map
                    def newCantExaImag = mapaExaCant.get("Imagenologicos") + examenesImagenologicosEpisodio.size()
                    def newCantExaLabo = mapaExaCant.get("Laboratorio") + examenesLaboratorioEpisodio.size()
                    mapaExaCant.put("Imagenologicos", newCantExaImag)
                    mapaExaCant.put("Laboratorio", newCantExaLabo)
                    mapaDiagnosticoExaCant.put(dignostico, mapaExaCant)
                }
            }
        }   
  
        // Llenos el array datos que enviare a la vista
        String[] datos = new String [cabFila1.opciones.length * cabColumna1.opciones.length]
        int indiceDatos = 0
        cabFila1.opciones.each{opCabFila1 ->
            LinkedHashMap<String, Integer> mapaExamenCantidad = mapaDiagnosticoExaCant.get(opCabFila1)
            cabColumna1.opciones.each{opCabColumna1 ->
                datos[indiceDatos++] = mapaExamenCantidad.get(opCabColumna1).toString()
            }
        }

        render(view: 'list', model:[
            nombreIndicador: message(code: 'indicadores.nombreIndicador.cantExamenesPorDiagnostico'),
            idIndicador: "cantExamenesPorDiagnostico",
            estructuraTabla: tablaResult,
            resDatos: datos,
            mostrarDatos: true,
            cantEpisodios: listaComp.size(),
            filtroCantDiagnosticos: true,
            cantidadDiagnosticos: obtenerCantDiagnosticos(params),
            fechaDesde: desde,
            fechaHasta: hasta])
    }

    //--------------------------------------------------------------------------

    int obtenerCantDiagnosticos(params){
        int cantDiagnosticos = 10
        if (params.cantidadDiagnosticos){
            cantDiagnosticos = Integer.valueOf(params.cantidadDiagnosticos)
        }
        return cantDiagnosticos
    }

    //--------------------------------------------------------------------------

    Date obtenerFechaDesde(params){
        Date hasta = new Date()
        Date desde = hasta-180
        if (params.fechaDesde_year && params.fechaDesde_month && params.fechaDesde_day){
            desde = new Date(Integer.valueOf(params.fechaDesde_year),
                             Integer.valueOf(params.fechaDesde_month),
                             Integer.valueOf(params.fechaDesde_day))
        }
        return desde
    }

    //--------------------------------------------------------------------------

    Date obtenerFechaHasta(params){
        Date hasta = new Date()
        if (params.fechaHasta_year && params.fechaHasta_month && params.fechaHasta_day){
            hasta = new Date(Integer.valueOf(params.fechaHasta_year),
                            Integer.valueOf(params.fechaHasta_month),
                            Integer.valueOf(params.fechaHasta_day),23,59,59)       
        }
        return hasta
    }

    //--------------------------------------------------------------------------

    String getStringFecha(Date fecha){
        String anio = fecha.year
        String mes = (fecha.month < 10) ? ("0" + fecha.month) : (fecha.month)
        String dia = (fecha.date < 10) ? ("0" + fecha.date) : (fecha.date)
        String hora = (fecha.hours < 10) ? ("0" + fecha.hours) : (fecha.hours)
        String min = (fecha.minutes < 10) ? ("0" + fecha.minutes) : (fecha.minutes)
        String seg = (fecha.seconds < 10) ? ("0" + fecha.seconds) : (fecha.seconds)
        return anio + "-" + mes + "-" + dia + " " + hora + ":" + min + ":" + seg
    }

    void imprimirObjetoXML(Object o){
        println "-----------------"
        XStream xstream = new XStream();
        String xml = xstream.toXML(o);
        println xml
        println "-----------------"
    }
}